# cython: language_level=3
import asyncio
from concurrent.futures import ThreadPoolExecutor

"""
Author: Gaoqiang Du
Description：Invoke synchronous methods asynchronously
Date: 2022/2/9 11:52
"""

executor = ThreadPoolExecutor()


async def sample_async(func, *args, **kwargs):
    def wrapper():
        return func(*args, **kwargs)

    loop = asyncio.get_event_loop()
    result = await loop.run_in_executor(executor, wrapper)
    return result


class AsyncWrapper:
    def __init__(self, subject, max_workers=None):
        self.subject = subject
        self.executor = ThreadPoolExecutor(max_workers=max_workers)

    def __getattr__(self, name):
        origin = getattr(self.subject, name)
        if callable(origin):
            def foo(*args, **kwargs):
                return self.run(origin, *args, **kwargs)

            # cache the function we built right now, to avoid later lookup
            self.__dict__[name] = foo
            return foo
        else:
            return origin

    async def run(self, origin_func, *args, **kwargs):
        def wrapper():
            return origin_func(*args, **kwargs)

        loop = asyncio.get_event_loop()
        return await loop.run_in_executor(self.executor, wrapper)
